#!usr/bin/env python  
# -*- coding:utf-8 _*-
""" 
@author:robot
@file: tmf_task.py 
@version:
@time: 2022/03/11 
"""
import time

from TapException.TM import *
from TapClientCore.T02_tm_api.v2_api.v2_tm import *
from TapClientCore.T03_api_body_templates.v2_api_body import *
from TapClientCore.T05_TM_feature.v2.TMF03_task.tmf_task_ws import ws_get_log
from TapUtil.decorator.some_useful import timeout
from TapUtil.logfunc.logger import logger

TM: [
    Api04Task,
    Api06SubTask,
] = v2tm


class TMFTask:
    task_type = None

    # _模型推演
    @staticmethod
    def _task_meta(payload):
        return TM.post_task_metadata(payload)

    # 模型推演
    def task_meta(self, payload):
        return self._task_meta(payload)

    # 创建任务
    @staticmethod
    def _send_task_payload(payload):
        return TM.patch_task_confirm(payload).get('data')

    #         数据复制报文构建
    @staticmethod
    def _build_task_copy_payload(conf):
        tmp = TASK_CREATE_DATA_COPY.copy()
        tmp.update(conf)
        return tmp

    #         _可观察性event数据获取
    @staticmethod
    def _build_measurement_payload(task_id):
        # response = TMFSubTask().get_subTask_measurement_info(task_id)
        # start = response.get('start')
        # sub_task_id = response.get('id')
        tmp = TASK_MEASUREMENT.copy()
        tmp['samples'][0]['tags']['taskId'] = task_id
        tmp['samples'][0]['start'] = time.time() * 1000
        tmp['samples'][1]['tags']['taskId'] = task_id
        tmp['statistics'][0]['tags']['taskId'] = task_id
        return tmp

    #         可观察性event数据获取
    def get_measurement_payload_task_id(self, task_id):
        return self._build_measurement_payload(task_id)

    #         子任务可观测性数据获取
    @staticmethod
    def post_measurement_payload(payload):
        return TMFSubTask().post_measurement_payload(payload)

    @staticmethod
    def get_measurement2_payload_task_id(task_id):
        import time
        _payload = {"samples": {"totalData": {"tags": {"type": "task", "taskId": task_id},
                                              "fields": ["inputInsertTotal", "inputUpdateTotal",
                                                         "inputDeleteTotal", "inputDdlTotal",
                                                         "inputOthersTotal", "outputInsertTotal",
                                                         "outputUpdateTotal", "outputDeleteTotal",
                                                         "outputDdlTotal", "outputOthersTotal"],
                                              "type": "instant"}},
                    "startAt": time.time() * 1000, "endAt": time.time() * 1000, }
        return _payload

    @staticmethod
    def post_measurement2_payload(payload):
        return TM.post_measurement_query_v2(payload)

    #         创建数据复制任务
    def create_task_data_copy(self, conf):
        payload = self._build_task_copy_payload(conf)
        return self._send_task_payload(payload)

    #         创建数据开发任务
    def create_task_data_development(self, conf):
        return self._send_task_payload(conf)

    #         任务名重复查询
    @staticmethod
    def task_check_name_repeat(task_name):
        return TM.post_task_check_name(task_name)

    #         任务更新
    @staticmethod
    def update_data_copy_by_id(task_id, payload):
        return TM.patch_task_confirm(payload, task_id)

    # 任务操作
    @staticmethod
    def operate_task_by_id(operate, task_id):
        if operate == 'start':
            TM.put_task_start_by_id(task_id)
        elif operate == 'stop':
            TM.put_task_stop_by_id(task_id)
        elif operate == 'delete':
            TM.delete_task_by_id(task_id)
        elif operate == 'reset':
            TM.patch_task_renew(task_id)

    # 通过id查询任务
    @staticmethod
    def query_task_by_id(task_id):
        return TM.get_task_by_id(task_id)

    # 通过任务名查询任务 - data copy
    @staticmethod
    def _query_data_copy(task_name, limit, skip):
        while True:
            filter = {
                "order": "createTime DESC",
                "limit": limit,
                "skip": skip,
                "fields": {
                    'id': True,
                    'name': True,
                    'status': True,
                    'stats': True,
                    'migrateModelStatus': True,
                    'syncType': True
                },
                "where": {"syncType": "migrate"}
            }
            response = TM.get_task_by_filter(filter)
            items = response.get('data').get('items')
            for one in items:
                if one.get('name') == task_name:
                    return one
            skip += limit
            if not items:
                break

    # 通过任务名查询任务 data - dev
    @staticmethod
    def _query_data_development(task_name, limit, skip):
        while True:
            filter2 = {
                "order": "createTime DESC",
                "limit": limit,
                "skip": skip,
                "fields": {
                    'id': True,
                    'name': True,
                    'status': True,
                    'stats': True,
                    'syncType': True
                },
                "where": {"syncType": "sync"}
            }
            response = TM.get_task_by_filter(filter2)
            items = response.get('data').get('items')
            for one in response.get('data').get('items'):
                if one.get('name') == task_name:
                    return one
            skip += limit
            if not items:
                break

    #     # 通过任务名查询任务
    def query_task_by_name(self, task_name):
        limit = 200
        skip = 0
        response = None
        if self.task_type == 'data copy':
            response = self._query_data_copy(task_name, limit, skip)
        elif self.task_type == 'data development':
            response = self._query_data_development(task_name, limit, skip)
        else:
            response = self._query_data_copy(task_name, limit, skip)
            if not response:
                skip = 0
                response = self._query_data_development(task_name, limit, skip)
        return response

    #   通过任务名，更新任务
    def update_data_copy_by_name(self, task_name, payload):
        query_result = self.query_task_by_name(task_name)
        task_response = self.query_task_by_id(query_result.get('id'))
        task_response.get('data').update(payload)
        self.update_data_copy_by_id(query_result.get('id'), task_response.get('data'))

    # 更具任务，节点名，更新任务
    def update_task_node_by_name(self, task_name, node_name, node_update):
        query_result = self.query_task_by_name(task_name)
        task_response = self.query_task_by_id(query_result.get('id'))
        for one in task_response.get('data').get('dag').get('nodes'):
            if one.get('name') == node_name:
                one.update(node_update)
                return self.update_data_copy_by_id(query_result.get('id'), task_response.get('data'))
        raise Exception('UPDATE NOT FAILED')

    # ws get subtask log
    # 获取任务日志
    @staticmethod
    def get_subtask_log(task_id):
        response = TMFSubTask().get_subTask_measurement_info(task_id)
        sub_task_id = response.get('id')
        raw_log = ws_get_log(v2tm.ws_uri, sub_task_id)
        for one_record in raw_log.get('data'):
            if one_record:
                one_record.pop('accessCode')
                one_record.pop('contextMap')
                one_record.pop('contextStack')
                one_record.pop('createTime')
                one_record.pop('createUser')
                one_record.pop('customId')
                one_record.pop('date')
                one_record.pop('hostname')
                one_record.pop('id')
                one_record.pop('ip')
                one_record.pop('lastUpdBy')
                one_record.pop('last_updated')
                one_record.pop('millis')
                one_record.pop('user_id')
                one_record.pop('uuid')
        return raw_log.get('data')

    # manage task status

    def manage_delete_task(self, task_name):
        query_result = self.query_task_by_name(task_name)
        self.operate_task_by_id('delete', query_result.get('id'))

    def manage_start_task(self, task_name):
        query_result = self.query_task_by_name(task_name)
        self.operate_task_by_id('start', query_result.get('id'))

    def manage_stop_task(self, task_name):
        query_result = self.query_task_by_name(task_name)
        self.operate_task_by_id('stop', query_result.get('id'))

    def manage_reset_task(self, task_name):
        query_result = self.query_task_by_name(task_name)
        self.operate_task_by_id('reset', query_result.get('id'))

    @timeout('modelDone', 50)
    def manage_wait_data_copy_model(self, task_name):
        query_result = self.query_task_by_name(task_name)
        return query_result.get('migrateModelStatus')

    @timeout(['running', 'complete'], 50)
    def manage_wait_task_to_running(self, task_name):
        query_result = self.query_task_by_name(task_name)
        if query_result.get('status') == 'error':
            logger.fatal('error')
            raise TaskError
        if query_result.get('status') == 'edit':
            raise TaskError
        return query_result.get('status')

    @timeout(['stop', 'complete'], 50)
    def manage_wait_task_to_stop(self, task_name):
        query_result = self.query_task_by_name(task_name)
        if query_result.get('status') == 'error':
            logger.fatal('error')
            raise TaskError
        return query_result.get('status')

    @timeout('complete', 50)
    def manage_wait_task_to_complete(self, task_name):
        query_result = self.query_task_by_name(task_name)
        if query_result.get('status') == 'error':
            logger.fatal('error')
            raise TaskError
        return query_result.get('status')

    def manage_stop_and_wait_stop(self, task_name):
        self.manage_stop_task(task_name)
        self.manage_wait_task_to_stop(task_name)

    def manage_force_stop(self, task_name):
        self.manage_force_stop(task_name)
        self.manage_wait_task_to_stop(task_name)

    def manage_start_and_wait_running(self, task_name):
        self.manage_start_task(task_name)
        self.manage_wait_task_to_running(task_name)

    def manage_start_and_wait_stop(self, task_name):
        self.manage_start_task(task_name)
        self.manage_wait_task_to_stop(task_name)

    def manage_start_and_wait_complete(self, task_name):
        self.manage_start_task(task_name)
        self.manage_wait_task_to_running(task_name)
        self.manage_wait_task_to_complete(task_name)


class TMFSubTask:

    @staticmethod
    def _get_subTask_by_task_id(task_id):
        return TM.get_subTask_by_task_id(task_id)

    @timeout('GET SUBTASK STATS', 20)
    def _get_subTask_measurement_info(self, task_id):
        response = self._get_subTask_by_task_id(task_id)
        data = response.get('data')[0]
        if data:
            if data.get('attrs').get('edgeMilestones'):
                self.data = data
                self.start_info = [v for k, v in data.get('attrs').get('edgeMilestones').items()]
                return 'GET SUBTASK STATS'

    def get_subTask_measurement_info(self, task_id):
        self._get_subTask_measurement_info(task_id)
        return {
            'start': self.start_info[0].get('milestones')[0].get('start'),
            'id': self.data.get('id')
        }

    @staticmethod
    def post_measurement_payload(payload):
        return TM.post_measurement_query(payload)


if __name__ == '__main__':
    T = TMFTask()
    res = T.query_task_by_name('sync_demo_auto_mysql_source2auto_mysql_targetB_MYSQL1660210742901702621')
    from pprint import pprint

    pprint(res)
